#include "monitorprocess.hpp"
#include "xmlparse.hpp"
#include "occipool.hpp"
#include "ftppool.hpp"
#include "thread.hpp"
#include "monitorservice.hpp"
#include <iostream>   
#include <fstream>
#include <sstream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "dbkeepalive.h"
#include <WinBase.h>

using std::cout;
using std::endl;
using std::ofstream;
using std::stringstream;
using namespace com_oocl_monitor::controller;
using namespace com_oocl_monitor::service;

MonitorProcess::MonitorProcess(const string& dbConfigFile,const string& emailConfigFile,const string &profileconfigFile)
:_dbConfigFile(dbConfigFile), _emailConfigFile(emailConfigFile),_profileConfigFile(profileconfigFile),_runTimeInfo(nullptr),_dbpool(nullptr),_ftpPools(map<string,FtpPool*>()){
	_sem=CreateSemaphore(NULL, MAXTHREADS, MAXTHREADS, NULL);
	init();
}

MonitorProcess::~MonitorProcess() {
	delete(_dbpool);
	delete(_runTimeInfo);
	for(auto it=_ftpPools.begin();it!=_ftpPools.end();++it)
		delete(it->second);
	CloseHandle(_sem);
}
void MonitorProcess::init(){
	loadDbConfig(_dbConfigFile);
	loadEmailConfig(_emailConfigFile);
	loadProfileConfig(_profileConfigFile);
	_dbpool=new OcciPool(_dbConfig._constr,_dbConfig._usr,_dbConfig._pwd,_dbConfig._maxCon,_dbConfig._minCon,_dbConfig._incrCon);
	for(auto it=_ftpProfileList.cbegin();it!=_ftpProfileList.cend();++it){
		_ftpPools.insert(std::pair<string,FtpPool*>(it->_ftpInfo._host+it->_ftpInfo._usr,
			new FtpPool(it->_ftpInfo._host,it->_ftpInfo._port,it->_ftpInfo._usr,it->_ftpInfo._pwd,it->_ftpInfo._maxCon)));
	}
}

void MonitorProcess::loadDbConfig(const string& dbConfigFile) {
	_xmlParse.parse(_dbConfig, dbConfigFile);
}
void MonitorProcess::loadEmailConfig(const string& emailConfigFile) {
	_xmlParse.parse(_emailConfig, emailConfigFile);
}
void MonitorProcess::loadProfileConfig(const string& profileConfigFile) {
	_xmlParse.parse(_ftpProfileList, profileConfigFile);
}

void MonitorProcess::run() {
    while (true) {
        DbKeepAlive keepAliveService(_dbpool);
        keepAliveService.run();
		HANDLE coutMutex = OpenMutex(MUTEX_ALL_ACCESS, false, TEXT("coutMutex"));
		WaitForSingleObject(coutMutex, INFINITE);
		cout << second_clock::local_time() << endl;
        cout << "Monitor is working!\n" << endl;
		ReleaseMutex(coutMutex);
		if (_runTimeInfo == nullptr)
			_runTimeInfo = new RunTimeInfo(_ftpProfileList, INTERVAL);
		else
			_runTimeInfo->load(_ftpProfileList, INTERVAL);
		for (auto it = _ftpProfileList.begin();it != _ftpProfileList.end();++it) {
			perFtpHost(*it);
		}
		WaitForSingleObject(coutMutex, INFINITE);
        cout<<"Main Thread is sleeping!\n"<<endl;
		ReleaseMutex(coutMutex);
		CloseHandle(coutMutex);
		Sleep(HAVEAREST);
    }
}

void MonitorProcess::perFtpHost(FtpProfile& ftpProfile) {
    for (auto it = ftpProfile._profiles.begin(); it !=ftpProfile._profiles.end(); ++it) {
        ptime lastTime = second_clock::local_time() - minutes(INTERVAL);
		string pfName = it->_profileName;
        if(_runTimeInfo->getStatus(pfName))
            continue;
        if (_runTimeInfo->getRuncount(pfName) != 0 || _runTimeInfo->getEndTime(pfName) <= lastTime) {
            Runnable *run = new MonitorService(ftpProfile._ftpInfo,*it,_emailConfig,_ftpPools.at(ftpProfile._ftpInfo._host+ftpProfile._ftpInfo._usr),_dbpool,_runTimeInfo);
            Thread t(run, &_sem);
            t.run();
        }
    }
}
